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

commit a0bcf90f35401d1b9902d1d06ac2c1cf40c0a442
Author:     Hermès Bélusca-Maïto <hermes.belusca-ma...@reactos.org>
AuthorDate: Thu May 19 23:19:04 2022 +0200
Commit:     Hermès Bélusca-Maïto <hermes.belusca-ma...@reactos.org>
CommitDate: Mon May 23 19:30:33 2022 +0200

    [NTOS:SE] SeValidSecurityDescriptor(): Add missing validation aspects 
(#4523)
    
    - Add extra bounds checks.
    - Add missing RtlValidAcl() calls for verifying the DACL and SACL.
---
 ntoskrnl/se/sd.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 8 deletions(-)

diff --git a/ntoskrnl/se/sd.c b/ntoskrnl/se/sd.c
index 56f013bf446..db3f5a5c440 100644
--- a/ntoskrnl/se/sd.c
+++ b/ntoskrnl/se/sd.c
@@ -1066,6 +1066,15 @@ SeValidSecurityDescriptor(
         return FALSE;
     }
 
+    /* Ensure the Owner SID is within the bounds of the security descriptor */
+    if ((SecurityDescriptor->Owner > Length) ||
+        (Length - SecurityDescriptor->Owner < sizeof(SID)))
+    {
+        DPRINT1("Owner SID not within bounds\n");
+        return FALSE;
+    }
+
+    /* Reference it */
     Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner);
     if (Sid->Revision != SID_REVISION)
     {
@@ -1073,6 +1082,7 @@ SeValidSecurityDescriptor(
         return FALSE;
     }
 
+    // NOTE: Same as SeLengthSid(Sid); but doesn't use hardcoded values.
     SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * sizeof(ULONG));
     if (Length < SdLength)
     {
@@ -1089,6 +1099,15 @@ SeValidSecurityDescriptor(
             return FALSE;
         }
 
+        /* Ensure the Group SID is within the bounds of the security 
descriptor */
+        if ((SecurityDescriptor->Group > Length) ||
+            (Length - SecurityDescriptor->Group < sizeof(SID)))
+        {
+            DPRINT1("Group SID not within bounds\n");
+            return FALSE;
+        }
+
+        /* Reference it */
         Sid = (PSID)((ULONG_PTR)SecurityDescriptor + 
SecurityDescriptor->Group);
         if (Sid->Revision != SID_REVISION)
         {
@@ -1096,6 +1115,7 @@ SeValidSecurityDescriptor(
             return FALSE;
         }
 
+        // NOTE: Same as SeLengthSid(Sid); but doesn't use hardcoded values.
         SdLength += (sizeof(SID) + (Sid->SubAuthorityCount - 1) * 
sizeof(ULONG));
         if (Length < SdLength)
         {
@@ -1113,20 +1133,29 @@ SeValidSecurityDescriptor(
             return FALSE;
         }
 
-        Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
-        if ((Acl->AclRevision < MIN_ACL_REVISION) ||
-            (Acl->AclRevision > MAX_ACL_REVISION))
+        /* Ensure the DACL is within the bounds of the security descriptor */
+        if ((SecurityDescriptor->Dacl > Length) ||
+            (Length - SecurityDescriptor->Dacl < sizeof(ACL)))
         {
-            DPRINT1("Invalid DACL revision\n");
+            DPRINT1("DACL not within bounds\n");
             return FALSE;
         }
 
+        /* Reference it */
+        Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
+
         SdLength += Acl->AclSize;
         if (Length < SdLength)
         {
             DPRINT1("Invalid DACL size\n");
             return FALSE;
         }
+
+        if (!RtlValidAcl(Acl))
+        {
+            DPRINT1("Invalid DACL\n");
+            return FALSE;
+        }
     }
 
     /* Check SACL */
@@ -1138,20 +1167,29 @@ SeValidSecurityDescriptor(
             return FALSE;
         }
 
-        Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
-        if ((Acl->AclRevision < MIN_ACL_REVISION) ||
-            (Acl->AclRevision > MAX_ACL_REVISION))
+        /* Ensure the SACL is within the bounds of the security descriptor */
+        if ((SecurityDescriptor->Sacl > Length) ||
+            (Length - SecurityDescriptor->Sacl < sizeof(ACL)))
         {
-            DPRINT1("Invalid SACL revision\n");
+            DPRINT1("SACL not within bounds\n");
             return FALSE;
         }
 
+        /* Reference it */
+        Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
+
         SdLength += Acl->AclSize;
         if (Length < SdLength)
         {
             DPRINT1("Invalid SACL size\n");
             return FALSE;
         }
+
+        if (!RtlValidAcl(Acl))
+        {
+            DPRINT1("Invalid SACL\n");
+            return FALSE;
+        }
     }
 
     return TRUE;

Reply via email to