(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 ***|
&LinkName,
OBJ_PERMANENT,
NULL,
- NULL);
+ &DosDevicesSD);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&LinkName,
OBJ_PERMANENT,
Handle,
- NULL);
+ &DosDevicesSD);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&LinkName,
OBJ_PERMANENT,
Handle,
- NULL);
+ &DosDevicesSD);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
/* 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
&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
*
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 */
}
}
+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,
}
/* 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;
/* Check create access for the object */
if (!ObCheckCreateObjectAccess(Directory,
- ObjectType == ObDirectoryType ?
+ ObjectType == ObpDirectoryObjectType ?
DIRECTORY_CREATE_SUBDIRECTORY :
DIRECTORY_CREATE_OBJECT,
AccessState,
/* 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,
Directory = NULL;
/* Increment the pointer count */
- InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
+ InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount, 1);
/* Cleanup from the first lookup */
ObpReleaseLookupContext(LookupContext);
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)
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 */