X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fob%2Fobname.c;h=460338f0d48e3a18f6b373e2447bd100199461f0;hp=9f0f1f2ae9ccb9f7e0898e99bef531c5d8ec180f;hb=33604e014768009d2c66c106d54d6d22945063fa;hpb=321bcc056d3a807b7c212f91663b592178f8b819 diff --git a/ntoskrnl/ob/obname.c b/ntoskrnl/ob/obname.c index 9f0f1f2ae9c..460338f0d48 100644 --- a/ntoskrnl/ob/obname.c +++ b/ntoskrnl/ob/obname.c @@ -29,29 +29,190 @@ 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; + NTSTATUS Status; + + /* Initialize the SD */ + Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); + ASSERT(NT_SUCCESS(Status)); + + 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 */ + Status = RtlCreateAcl(Dacl, AclSize, ACL_REVISION); + ASSERT(NT_SUCCESS(Status)); + + /* Add the ACEs */ + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + GENERIC_READ | GENERIC_EXECUTE, + SeWorldSid); + ASSERT(NT_SUCCESS(Status)); + + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + GENERIC_ALL, + SeLocalSystemSid); + ASSERT(NT_SUCCESS(Status)); + + Status = RtlAddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + GENERIC_EXECUTE, + SeWorldSid); + ASSERT(NT_SUCCESS(Status)); + + Status = RtlAddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + GENERIC_ALL, + SeAliasAdminsSid); + ASSERT(NT_SUCCESS(Status)); + + Status = RtlAddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + GENERIC_ALL, + SeLocalSystemSid); + ASSERT(NT_SUCCESS(Status)); + + Status = RtlAddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + GENERIC_ALL, + SeCreatorOwnerSid); + ASSERT(NT_SUCCESS(Status)); + } + 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 */ + Status = RtlCreateAcl(Dacl, AclSize, ACL_REVISION); + ASSERT(NT_SUCCESS(Status)); + + /* Add the ACEs */ + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + GENERIC_READ | GENERIC_EXECUTE | GENERIC_WRITE, + SeWorldSid); + ASSERT(NT_SUCCESS(Status)); + + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + GENERIC_ALL, + SeLocalSystemSid); + ASSERT(NT_SUCCESS(Status)); + + Status = RtlAddAccessAllowedAceEx(Dacl, + ACL_REVISION, + INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, + GENERIC_ALL, + SeWorldSid); + ASSERT(NT_SUCCESS(Status)); + } + + /* Attach the DACL to the SD */ + Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, Dacl, FALSE); + ASSERT(NT_SUCCESS(Status)); + + return STATUS_SUCCESS; +} + INIT_FUNCTION +VOID +NTAPI +ObpFreeDosDevicesProtection(OUT PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + PACL Dacl; + NTSTATUS Status; + BOOLEAN DaclPresent, DaclDefaulted; + + Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted); + ASSERT(NT_SUCCESS(Status)); + ASSERT(DaclPresent); + ASSERT(Dacl != NULL); + ExFreePoolWithTag(Dacl, 'lcaD'); +} + +INIT_FUNCTION +NTSTATUS +NTAPI ObpCreateDosDevicesDirectory(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING RootName, TargetName, LinkName; HANDLE Handle, SymHandle; + SECURITY_DESCRIPTOR DosDevicesSD; NTSTATUS Status; + /* + * Enable LUID mappings only if not explicitely disabled + * and if protection mode is set + */ + if (ObpProtectionMode == 0 || ObpLUIDDeviceMapsDisabled != 0) + ObpLUIDDeviceMapsEnabled = 0; + else + ObpLUIDDeviceMapsEnabled = 1; + + /* 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??"); InitializeObjectAttributes(&ObjectAttributes, &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 +223,7 @@ ObpCreateDosDevicesDirectory(VOID) &LinkName, OBJ_PERMANENT, NULL, - NULL); + &DosDevicesSD); Status = NtCreateSymbolicLinkObject(&SymHandle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, @@ -83,7 +244,7 @@ ObpCreateDosDevicesDirectory(VOID) &LinkName, OBJ_PERMANENT, Handle, - NULL); + &DosDevicesSD); Status = NtCreateSymbolicLinkObject(&SymHandle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, @@ -101,7 +262,7 @@ ObpCreateDosDevicesDirectory(VOID) &LinkName, OBJ_PERMANENT, Handle, - NULL); + &DosDevicesSD); Status = NtCreateSymbolicLinkObject(&SymHandle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, @@ -110,7 +271,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 +285,20 @@ 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: + ObpFreeDosDevicesProtection(&DosDevicesSD); /* 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,7 +366,7 @@ ObpDeleteNameCheck(IN PVOID Object) ObpDeleteEntryDirectory(&Context); /* Check if this is a symbolic link */ - if (ObjectType == ObSymbolicLinkType) + if (ObjectType == ObpSymbolicLinkObjectType) { /* Remove internal name */ ObpDeleteSymbolicLinkName(Object); @@ -302,10 +413,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 +544,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 +855,7 @@ ParseFromRoot: /* Check create access for the object */ if (!ObCheckCreateObjectAccess(Directory, - ObjectType == ObDirectoryType ? + ObjectType == ObpDirectoryObjectType ? DIRECTORY_CREATE_SUBDIRECTORY : DIRECTORY_CREATE_OBJECT, AccessState, @@ -710,11 +871,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 +960,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 +1114,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 +1399,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 */