Author: pschweitzer Date: Sun Dec 28 10:05:29 2014 New Revision: 65856
URL: http://svn.reactos.org/svn/reactos?rev=65856&view=rev Log: [NTOSKRNL] - Implement IopGetDeviceAttachmentBase() which allows getting the base device of the device stack given any device object in it - Implement IopGetDevicePDO() which returns the physical device object of the device stack given any device object in it - Implement IopSetDeviceSecurityDescriptor() which will swap the old security descriptor of a device object with a new provided one - Implement IopSetDeviceSecurityDescriptors() which will swap the old security descriptor with a new provided one in all the device objects from the lowest provided to the uppest provided one. - Fix a fixme in IopGetSetSecurityObject(), the operation SetSecurityDescriptor is now fully implemented for both PDO & DO.
This is required by VMware driver vmci.sys. Even though, the installation doesn't get any better; it just changes the BSOD, we now face a memory corruption (in SE).
CORE-7991
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/file.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/io/iomgr/file.c [iso-8859-1] Sun Dec 28 10:05:29 2014 @@ -14,6 +14,8 @@ #include <ntoskrnl.h> #define NDEBUG #include <debug.h> + +extern ERESOURCE IopSecurityResource;
/* PRIVATE FUNCTIONS *********************************************************/
@@ -1308,6 +1310,174 @@ } }
+PDEVICE_OBJECT +NTAPI +IopGetDeviceAttachmentBase(PDEVICE_OBJECT DeviceObject) +{ + PDEVICE_OBJECT PDO = DeviceObject; + + /* Go down the stack to attempt to get the PDO */ + for (; ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo != NULL; + PDO = ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo); + + return PDO; +} + +PDEVICE_OBJECT +NTAPI +IopGetDevicePDO(PDEVICE_OBJECT DeviceObject) +{ + KIRQL OldIrql; + PDEVICE_OBJECT PDO; + + ASSERT(DeviceObject != NULL); + + OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock); + /* Get the base DO */ + PDO = IopGetDeviceAttachmentBase(DeviceObject); + /* Check whether that's really a PDO and if so, keep it */ + if ((PDO->Flags & DO_BUS_ENUMERATED_DEVICE) != DO_BUS_ENUMERATED_DEVICE) + { + PDO = NULL; + } + else + { + ObReferenceObject(PDO); + } + KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql); + + return PDO; +} + +NTSTATUS +NTAPI +IopSetDeviceSecurityDescriptor(IN PDEVICE_OBJECT DeviceObject, + IN PSECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN POOL_TYPE PoolType, + IN PGENERIC_MAPPING GenericMapping) +{ + NTSTATUS Status; + PSECURITY_DESCRIPTOR OldSecurityDescriptor, CachedSecurityDescriptor, NewSecurityDescriptor; + + PAGED_CODE(); + + /* Keep attempting till we find our old SD or fail */ + while (TRUE) + { + KeEnterCriticalRegion(); + ExAcquireResourceSharedLite(&IopSecurityResource, TRUE); + + /* Get our old SD and reference it */ + OldSecurityDescriptor = DeviceObject->SecurityDescriptor; + if (OldSecurityDescriptor != NULL) + { + ObReferenceSecurityDescriptor(OldSecurityDescriptor, 1); + } + + ExReleaseResourceLite(&IopSecurityResource); + KeLeaveCriticalRegion(); + + /* Set the SD information */ + NewSecurityDescriptor = OldSecurityDescriptor; + Status = SeSetSecurityDescriptorInfo(NULL, SecurityInformation, + SecurityDescriptor, &NewSecurityDescriptor, + PoolType, GenericMapping); + + if (!NT_SUCCESS(Status)) + { + if (OldSecurityDescriptor != NULL) + { + ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1); + } + + break; + } + + /* Add the new DS to the internal cache */ + Status = ObLogSecurityDescriptor(NewSecurityDescriptor, + &CachedSecurityDescriptor, 1); + ExFreePool(NewSecurityDescriptor); + if (!NT_SUCCESS(Status)) + { + ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1); + break; + } + + KeEnterCriticalRegion(); + ExAcquireResourceSharedLite(&IopSecurityResource, TRUE); + /* Check if someone changed it in our back */ + if (DeviceObject->SecurityDescriptor == OldSecurityDescriptor) + { + /* We're clear, do the swap */ + DeviceObject->SecurityDescriptor = CachedSecurityDescriptor; + ExReleaseResourceLite(&IopSecurityResource); + KeLeaveCriticalRegion(); + + /* And dereference old SD (twice - us + not in use) */ + ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 2); + + break; + } + ExReleaseResourceLite(&IopSecurityResource); + KeLeaveCriticalRegion(); + + /* If so, try again */ + ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1); + ObDereferenceSecurityDescriptor(CachedSecurityDescriptor, 1); + } + + return Status; +} + +NTSTATUS +NTAPI +IopSetDeviceSecurityDescriptors(IN PDEVICE_OBJECT UpperDeviceObject, + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PSECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN POOL_TYPE PoolType, + IN PGENERIC_MAPPING GenericMapping) +{ + PDEVICE_OBJECT CurrentDO = PhysicalDeviceObject, NextDevice; + NTSTATUS Status = STATUS_SUCCESS, TmpStatus; + + PAGED_CODE(); + + ASSERT(PhysicalDeviceObject != NULL); + + /* We always reference the DO we're working on */ + ObReferenceObject(CurrentDO); + + /* Go up from PDO to latest DO */ + do + { + /* Attempt to set the new SD on it */ + TmpStatus = IopSetDeviceSecurityDescriptor(CurrentDO, SecurityInformation, + SecurityDescriptor, PoolType, + GenericMapping); + /* Was our last one? Remember that status then */ + if (CurrentDO == UpperDeviceObject) + { + Status = TmpStatus; + } + + /* Try to move to the next DO (and thus, reference it) */ + NextDevice = CurrentDO->AttachedDevice; + if (NextDevice) + { + ObReferenceObject(NextDevice); + } + + /* Dereference current DO and move to the next one */ + ObDereferenceObject(CurrentDO); + CurrentDO = NextDevice; + } + while (CurrentDO != NULL); + + return Status; +} + NTSTATUS NTAPI IopGetSetSecurityObject(IN PVOID ObjectBody, @@ -1385,11 +1555,34 @@ /* Return success */ return STATUS_SUCCESS; } - else - { - DPRINT1("FIXME: Set SD unimplemented for Devices\n"); + else if (OperationCode == SetSecurityDescriptor) + { + /* Get the Physical Device Object if any */ + PDEVICE_OBJECT PDO = IopGetDevicePDO(DeviceObject); + + if (PDO != NULL) + { + /* Apply the new SD to any DO in the path from PDO to current DO */ + Status = IopSetDeviceSecurityDescriptors(DeviceObject, PDO, + SecurityInformation, + SecurityDescriptor, + PoolType, GenericMapping); + ObDereferenceObject(PDO); + } + else + { + /* Otherwise, just set for ourselves */ + Status = IopSetDeviceSecurityDescriptor(DeviceObject, + SecurityInformation, + SecurityDescriptor, + PoolType, GenericMapping); + } + return STATUS_SUCCESS; } + + /* Shouldn't happen */ + return STATUS_SUCCESS; } else if (OperationCode == DeleteSecurityDescriptor) {