[NTOSKRNL] Modify ObpCreateDeviceMap so that it can handle any process
[reactos.git] / ntoskrnl / ob / obname.c
index 7f6274d..6c99613 100644 (file)
@@ -29,17 +29,135 @@ UNICODE_STRING ObpDosDevicesShortName =
     (PWSTR)&ObpDosDevicesShortNamePrefix
 };
 
+WCHAR ObpUnsecureGlobalNamesBuffer[128] = {0};
+ULONG ObpUnsecureGlobalNamesLength = sizeof(ObpUnsecureGlobalNamesBuffer);
+
 /* PRIVATE FUNCTIONS *********************************************************/
 
+INIT_FUNCTION
 NTSTATUS
 NTAPI
+ObpGetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR SecurityDescriptor)
+{
+    PACL Dacl;
+    ULONG AclSize;
+
+    /* Initialize the SD */
+    RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
+
+    if (ObpProtectionMode & 1)
+    {
+        AclSize = sizeof(ACL) +
+                  sizeof(ACE) + RtlLengthSid(SeWorldSid) +
+                  sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
+                  sizeof(ACE) + RtlLengthSid(SeWorldSid) +
+                  sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid) +
+                  sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
+                  sizeof(ACE) + RtlLengthSid(SeCreatorOwnerSid);
+
+        /* Allocate the ACL */
+        Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, 'lcaD');
+        if (Dacl == NULL)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        /* Initialize the DACL */
+        RtlCreateAcl(Dacl, AclSize, ACL_REVISION);
+
+        /* Add the ACEs */
+        RtlAddAccessAllowedAce(Dacl,
+                               ACL_REVISION,
+                               GENERIC_READ | GENERIC_EXECUTE,
+                               SeWorldSid);
+
+        RtlAddAccessAllowedAce(Dacl,
+                               ACL_REVISION,
+                               GENERIC_ALL,
+                               SeLocalSystemSid);
+
+        RtlAddAccessAllowedAceEx(Dacl,
+                                 ACL_REVISION,
+                                 INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+                                 GENERIC_EXECUTE,
+                                 SeWorldSid);
+
+        RtlAddAccessAllowedAceEx(Dacl,
+                                 ACL_REVISION,
+                                 INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+                                 GENERIC_ALL,
+                                 SeAliasAdminsSid);
+
+        RtlAddAccessAllowedAceEx(Dacl,
+                                 ACL_REVISION,
+                                 INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+                                 GENERIC_ALL,
+                                 SeLocalSystemSid);
+
+        RtlAddAccessAllowedAceEx(Dacl,
+                                 ACL_REVISION,
+                                 INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+                                 GENERIC_ALL,
+                                 SeCreatorOwnerSid);
+    }
+    else
+    {
+        AclSize = sizeof(ACL) +
+                  sizeof(ACE) + RtlLengthSid(SeLocalSystemSid) +
+                  sizeof(ACE) + RtlLengthSid(SeWorldSid) +
+                  sizeof(ACE) + RtlLengthSid(SeLocalSystemSid);
+
+        /* Allocate the ACL */
+        Dacl = ExAllocatePoolWithTag(PagedPool, AclSize, 'lcaD');
+        if (Dacl == NULL)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        /* Initialize the DACL */
+        RtlCreateAcl(Dacl, AclSize, ACL_REVISION);
+
+        /* Add the ACEs */
+        RtlAddAccessAllowedAce(Dacl,
+                               ACL_REVISION,
+                               GENERIC_READ | GENERIC_EXECUTE | GENERIC_WRITE,
+                               SeWorldSid);
+
+        RtlAddAccessAllowedAce(Dacl,
+                               ACL_REVISION,
+                               GENERIC_ALL,
+                               SeLocalSystemSid);
+
+        RtlAddAccessAllowedAceEx(Dacl,
+                                 ACL_REVISION,
+                                 INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
+                                 GENERIC_ALL,
+                                 SeWorldSid);
+    }
+
+    /* Attach the DACL to the SD */
+    RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, Dacl, FALSE);
+
+    return STATUS_SUCCESS;
+}
+
 INIT_FUNCTION
+NTSTATUS
+NTAPI
 ObpCreateDosDevicesDirectory(VOID)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING RootName, TargetName, LinkName;
     HANDLE Handle, SymHandle;
+    SECURITY_DESCRIPTOR DosDevicesSD;
     NTSTATUS Status;
+    PACL Dacl;
+    BOOLEAN DaclPresent, DaclDefaulted;
+
+    /* Create a custom security descriptor for the global DosDevices directory */
+    Status = ObpGetDosDevicesProtection(&DosDevicesSD);
+    if (!NT_SUCCESS(Status))
+        return Status;
 
     /* Create the global DosDevices directory \?? */
     RtlInitUnicodeString(&RootName, L"\\GLOBAL??");
@@ -47,11 +165,17 @@ ObpCreateDosDevicesDirectory(VOID)
                                &RootName,
                                OBJ_PERMANENT,
                                NULL,
-                               NULL);
+                               &DosDevicesSD);
     Status = NtCreateDirectoryObject(&Handle,
                                      DIRECTORY_ALL_ACCESS,
                                      &ObjectAttributes);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+        goto done;
+
+    /* Create the system device map */
+    Status = ObSetDeviceMap(NULL, Handle);
+    if (!NT_SUCCESS(Status))
+        goto done;
 
     /*********************************************\
     |*** HACK until we support device mappings ***|
@@ -62,7 +186,7 @@ ObpCreateDosDevicesDirectory(VOID)
                                &LinkName,
                                OBJ_PERMANENT,
                                NULL,
-                               NULL);
+                               &DosDevicesSD);
     Status = NtCreateSymbolicLinkObject(&SymHandle,
                                         SYMBOLIC_LINK_ALL_ACCESS,
                                         &ObjectAttributes,
@@ -83,7 +207,7 @@ ObpCreateDosDevicesDirectory(VOID)
                                &LinkName,
                                OBJ_PERMANENT,
                                Handle,
-                               NULL);
+                               &DosDevicesSD);
     Status = NtCreateSymbolicLinkObject(&SymHandle,
                                         SYMBOLIC_LINK_ALL_ACCESS,
                                         &ObjectAttributes,
@@ -101,7 +225,7 @@ ObpCreateDosDevicesDirectory(VOID)
                                &LinkName,
                                OBJ_PERMANENT,
                                Handle,
-                               NULL);
+                               &DosDevicesSD);
     Status = NtCreateSymbolicLinkObject(&SymHandle,
                                         SYMBOLIC_LINK_ALL_ACCESS,
                                         &ObjectAttributes,
@@ -110,7 +234,8 @@ ObpCreateDosDevicesDirectory(VOID)
 
     /* Close the directory handle */
     NtClose(Handle);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+        goto done;
 
     /*
      * Initialize the \DosDevices symbolic link pointing to the global
@@ -123,71 +248,21 @@ ObpCreateDosDevicesDirectory(VOID)
                                &LinkName,
                                OBJ_PERMANENT,
                                NULL,
-                               NULL);
+                               &DosDevicesSD);
     Status = NtCreateSymbolicLinkObject(&SymHandle,
                                         SYMBOLIC_LINK_ALL_ACCESS,
                                         &ObjectAttributes,
                                         &RootName);
     if (NT_SUCCESS(Status)) NtClose(SymHandle);
 
-    /* FIXME: Hack Hack! */
-    ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool,
-                                              sizeof(*ObSystemDeviceMap),
-                                              'mDbO');
-    if (!ObSystemDeviceMap) return STATUS_INSUFFICIENT_RESOURCES;
-    RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
+done:
+    RtlGetDaclSecurityDescriptor(&DosDevicesSD, &DaclPresent, &Dacl, &DaclDefaulted);
+    ExFreePoolWithTag(Dacl, 'lcaD');
 
     /* Return status */
     return Status;
 }
 
-VOID
-NTAPI
-ObDereferenceDeviceMap(IN PEPROCESS Process)
-{
-    PDEVICE_MAP DeviceMap;
-
-    /* Get the pointer to this process devicemap and reset it
-       holding devicemap lock */
-    KeAcquireGuardedMutex(&ObpDeviceMapLock);
-    DeviceMap = Process->DeviceMap;
-    Process->DeviceMap = NULL;
-    KeReleaseGuardedMutex(&ObpDeviceMapLock);
-
-    /* Continue only if there is a devicemap to dereference */
-    if (DeviceMap)
-    {
-        KeAcquireGuardedMutex(&ObpDeviceMapLock);
-
-        /* Delete the device map link and dereference it */
-        if (--DeviceMap->ReferenceCount)
-        {
-            /* Nobody is referencing it anymore, unlink the DOS directory */
-            DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
-
-            /* Release the devicemap lock */
-            KeReleaseGuardedMutex(&ObpDeviceMapLock);
-
-            /* Dereference the DOS Devices Directory and free the Device Map */
-            ObDereferenceObject(DeviceMap->DosDevicesDirectory);
-            ExFreePool(DeviceMap);
-        }
-        else
-        {
-            /* Release the devicemap lock */
-            KeReleaseGuardedMutex(&ObpDeviceMapLock);
-        }
-    }
-}
-
-VOID
-NTAPI
-ObInheritDeviceMap(IN PEPROCESS Parent,
-                   IN PEPROCESS Process)
-{
-    /* FIXME: Devicemap Support */
-}
-
 /*++
 * @name ObpDeleteNameCheck
 *
@@ -255,20 +330,20 @@ ObpDeleteNameCheck(IN PVOID Object)
                 ObpDeleteEntryDirectory(&Context);
 
                 /* Check if this is a symbolic link */
-                if (ObjectType == ObSymbolicLinkType)
+                if (ObjectType == ObpSymbolicLinkObjectType)
                 {
                     /* Remove internal name */
                     ObpDeleteSymbolicLinkName(Object);
                 }
 
-                /* Check if the magic protection flag is set */
+                /* Check if the kernel exclusive is set */
                 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
                 if ((ObjectNameInfo) &&
-                    (ObjectNameInfo->QueryReferences & 0x40000000))
+                    (ObjectNameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE))
                 {
                     /* Remove protection flag */
                     InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
-                                           -0x40000000);
+                                           -OB_FLAG_KERNEL_EXCLUSIVE);
                 }
 
                 /* Get the directory */
@@ -302,10 +377,60 @@ ObpDeleteNameCheck(IN PVOID Object)
     }
 }
 
+BOOLEAN
+NTAPI
+ObpIsUnsecureName(IN PUNICODE_STRING ObjectName,
+                  IN BOOLEAN CaseInSensitive)
+{
+    BOOLEAN Unsecure;
+    PWSTR UnsecureBuffer;
+    UNICODE_STRING UnsecureName;
+
+    /* No unsecure names known, quit */
+    if (ObpUnsecureGlobalNamesBuffer[0] == UNICODE_NULL)
+    {
+        return FALSE;
+    }
+
+    /* By default, we have a secure name */
+    Unsecure = FALSE;
+    /* We will browse the whole string */
+    UnsecureBuffer = &ObpUnsecureGlobalNamesBuffer[0];
+    while (TRUE)
+    {
+        /* Initialize the unicode string */
+        RtlInitUnicodeString(&UnsecureName, UnsecureBuffer);
+        /* We're at the end of the multisz string! */
+        if (UnsecureName.Length == 0)
+        {
+            break;
+        }
+
+        /*
+         * Does the unsecure name prefix the object name?
+         * If so, that's an unsecure name, and return so
+         */
+        if (RtlPrefixUnicodeString(&UnsecureName, ObjectName, CaseInSensitive))
+        {
+            Unsecure = TRUE;
+            break;
+        }
+
+        /*
+         * Move to the next string. As a reminder, ObpUnsecureGlobalNamesBuffer is
+         * a multisz, so we move the string next to the current UNICODE_NULL char
+         */
+        UnsecureBuffer = (PWSTR)((ULONG_PTR)UnsecureBuffer + UnsecureName.Length + sizeof(UNICODE_NULL));
+    }
+
+    /* Return our findings */
+    return Unsecure;
+}
+
 NTSTATUS
 NTAPI
 ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL,
-                    IN PUNICODE_STRING ObjectName,
+                    IN OUT PUNICODE_STRING ObjectName,
                     IN ULONG Attributes,
                     IN POBJECT_TYPE ObjectType,
                     IN KPROCESSOR_MODE AccessMode,
@@ -383,7 +508,7 @@ ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL,
         }
 
         /* Don't parse a Directory */
-        if (ObjectHeader->Type != ObDirectoryType)
+        if (ObjectHeader->Type != ObpDirectoryObjectType)
         {
             /* Make sure the Object Type has a parse routine */
             ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure;
@@ -694,7 +819,7 @@ ParseFromRoot:
 
                 /* Check create access for the object */
                 if (!ObCheckCreateObjectAccess(Directory,
-                                               ObjectType == ObDirectoryType ?
+                                               ObjectType == ObpDirectoryObjectType ?
                                                DIRECTORY_CREATE_SUBDIRECTORY :
                                                DIRECTORY_CREATE_OBJECT,
                                                AccessState,
@@ -710,11 +835,27 @@ ParseFromRoot:
                 /* Get the object header */
                 ObjectHeader = OBJECT_TO_OBJECT_HEADER(InsertObject);
 
-                /* FIXME: Check if this is a Section Object or Sym Link */
-                /* FIXME: If it is, then check if this isn't session 0 */
-                /* FIXME: If it isn't, check for SeCreateGlobalPrivilege */
-                /* FIXME: If privilege isn't there, check for unsecure name */
-                /* FIXME: If it isn't a known unsecure name, then fail */
+                /*
+                 * Deny object creation if:
+                 * That's a section object or a symbolic link
+                 * Which isn't in the same section that root directory
+                 * That doesn't have the SeCreateGlobalPrivilege
+                 * And that is not a known unsecure name
+                 */
+                if (RootDirectory->SessionId != -1)
+                {
+                    if (ObjectHeader->Type == MmSectionObjectType ||
+                        ObjectHeader->Type == ObpSymbolicLinkObjectType)
+                    {
+                        if (RootDirectory->SessionId != PsGetCurrentProcessSessionId() &&
+                            !SeSinglePrivilegeCheck(SeCreateGlobalPrivilege, AccessCheckMode) &&
+                            !ObpIsUnsecureName(&ComponentName, BooleanFlagOn(Attributes, OBJ_CASE_INSENSITIVE)))
+                        {
+                            Status = STATUS_ACCESS_DENIED;
+                            break;
+                        }
+                    }
+                }
 
                 /* Create Object Name */
                 NewName = ExAllocatePoolWithTag(PagedPool,
@@ -783,7 +924,7 @@ ReparseObject:
                 Directory = NULL;
 
                 /* Increment the pointer count */
-                InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
+                InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1);
 
                 /* Cleanup from the first lookup */
                 ObpReleaseLookupContext(LookupContext);
@@ -937,7 +1078,7 @@ ReparseObject:
                 else
                 {
                     /* We still have a name; check if this is a directory object */
-                    if (ObjectHeader->Type == ObDirectoryType)
+                    if (ObjectHeader->Type == ObpDirectoryObjectType)
                     {
                         /* Check if we have a referenced parent directory */
                         if (ReferencedParentDirectory)
@@ -1222,51 +1363,4 @@ ObQueryNameString(IN PVOID Object,
     return Status;
 }
 
-VOID
-NTAPI
-ObQueryDeviceMapInformation(IN PEPROCESS Process,
-                            IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
-{
-    /*
-    * FIXME: This is an ugly hack for now, to always return the System Device Map
-    * instead of returning the Process Device Map. Not important yet since we don't use it
-    */
-
-    KeAcquireGuardedMutex(&ObpDeviceMapLock);
-
-    /* Make a copy */
-    DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
-    RtlCopyMemory(DeviceMapInfo->Query.DriveType,
-                  ObSystemDeviceMap->DriveType,
-                  sizeof(ObSystemDeviceMap->DriveType));
-
-    KeReleaseGuardedMutex(&ObpDeviceMapLock);
-}
-
-NTSTATUS
-NTAPI
-ObIsDosDeviceLocallyMapped(
-    IN ULONG Index,
-    OUT PUCHAR DosDeviceState)
-{
-    /* check parameters */
-    if (Index < 1 || Index > 26)
-    {
-        /* invalid index */
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* acquire lock */
-    KeAcquireGuardedMutex(&ObpDeviceMapLock);
-
-    /* get drive mapping status */
-    *DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
-
-    /* release lock */
-    KeReleaseGuardedMutex(&ObpDeviceMapLock);
-
-    /* done */
-    return STATUS_SUCCESS;
-}
-
 /* EOF */